package com.koomii.common.util;
import org.apache.commons.beanutils.BeanUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * Describe:操作日志相关
 * User:
 * Date: May 31, 2010
 * Time: 3:22:53 PM
 */
public class OperateLogUtil {
	private static String testXml = "<?xml version=\"1.0\" encoding=\"GBK\"?><history><class name=\"DeliveryFeeContract\"><record id=\"46\"><field name=\"chargeType\"><changed>N</changed><oldvalue>2</oldvalue><newvalue>2</newvalue></field><field name=\"signoffFee\"><changed>N</changed><oldvalue>666.00</oldvalue><newvalue>666.00</newvalue></field><field name=\"signoffWeight\"><changed>Y</changed><oldvalue>777.0</oldvalue><newvalue>665.0</newvalue></field><field name=\"signoffFeeHigh\"><changed>N</changed><oldvalue>888.00</oldvalue><newvalue>888.00</newvalue></field><field name=\"rejectFee\"><changed>N</changed><oldvalue>1.00</oldvalue><newvalue>1.00</newvalue></field><field name=\"rejectWeight\"><changed>N</changed><oldvalue>1.0</oldvalue><newvalue>1.0</newvalue></field><field name=\"rejectFeeHigh\"><changed>N</changed><oldvalue>1.00</oldvalue><newvalue>1.00</newvalue></field><field name=\"returnFee\"><changed>N</changed><oldvalue>1.00</oldvalue><newvalue>1.00</newvalue></field><field name=\"returnWeight\"><changed>N</changed><oldvalue>1.0</oldvalue><newvalue>1.0</newvalue></field><field name=\"returnFeeHigh\"><changed>N</changed><oldvalue>1.00</oldvalue><newvalue>1.00</newvalue></field></record><record id=\"47\"><field name=\"chargeType\"><changed>N</changed><oldvalue>1</oldvalue><newvalue>1</newvalue></field><field name=\"signoffFee\"><changed>N</changed><oldvalue>888.00</oldvalue><newvalue>888.00</newvalue></field><field name=\"signoffWeight\"><changed>Y</changed><oldvalue>777.0</oldvalue><newvalue>776.0</newvalue></field><field name=\"signoffFeeHigh\"><changed>N</changed><oldvalue>88.00</oldvalue><newvalue>88.00</newvalue></field><field name=\"rejectFee\"><changed>N</changed><oldvalue>3.00</oldvalue><newvalue>3.00</newvalue></field><field name=\"rejectWeight\"><changed>N</changed><oldvalue>3.0</oldvalue><newvalue>3.0</newvalue></field><field name=\"rejectFeeHigh\"><changed>N</changed><oldvalue>4.00</oldvalue><newvalue>4.00</newvalue></field><field name=\"returnFee\"><changed>N</changed><oldvalue>55.00</oldvalue><newvalue>55.00</newvalue></field><field name=\"returnWeight\"><changed>N</changed><oldvalue>5.0</oldvalue><newvalue>5.0</newvalue></field><field name=\"returnFeeHigh\"><changed>N</changed><oldvalue>5.00</oldvalue><newvalue>5.00</newvalue></field></record></class></history>";
	/**
	 * 生成类对应的xml
	 * objectListMap:Map<String, List<Object[]>,Map的key值为数据库表对应的类名,value值为存放Object[]对象的List,Object[]为长度为2的数组,Object[0]修改前的对象,Object[1]修改后的对象
	 * logIfEqual：字段值若相等时是否生成字段信息到xml中
	 * filedNames:需判断的字段名,逗号分隔

	 * @return
	 */
	public static String generateHistoryClassXml(Map<String, List<Object[]>> objectListMap, boolean logIfEqual, String filedNames) throws Exception {
		StringBuffer sb = new StringBuffer();
		Object o1, o2;
		List<Object[]> objectList;
		for (String key : objectListMap.keySet()) {
			sb.append("<class name=\"").append(key).append("\">");
			objectList = objectListMap.get(key);
			for (Object[] objectArr : objectList) {
				o1 = objectArr[0];
				o2 = objectArr[1];
				sb.append(generateRecordXml(o1, o2, logIfEqual, filedNames));
			}
			sb.append("</class>");
		}
		return getXmlHead() + sb.toString() + getXmlBottom();
	}
	private static String getXmlHead() {
		return "<?xml version=\"1.0\" encoding=\"GBK\"?><history>";
	}
	private static String getXmlBottom() {
		return "</history>";
	}
	/**
	 * 生成record对应的xml
	 * @param o1
	 * @param o2
	 * @param logIfEqual
	 * @param filedNames
	 * @return
	 * @throws Exception
	 */
	private static String generateRecordXml(Object o1, Object o2, boolean logIfEqual, String filedNames) throws Exception {
		StringBuffer sb = new StringBuffer("<record id=\"").append(BeanUtils.getProperty(o1, "id")).append("\">");
		String[] fieldNameArr = filedNames.split(",");
		for (int i = 0; i < fieldNameArr.length; i++) {
			sb.append(generateFieldXml(fieldNameArr[i], o1, o2, logIfEqual));
		}
		sb.append("</record>");
		return sb.toString();
	}
	/**
	 * 生成字段对应的xml
	 * @param name
	 * @param o1
	 * @param o2
	 * @param logIfEqual
	 * @return
	 * @throws Exception
	 */
	private static String generateFieldXml(String name, Object o1, Object o2, boolean logIfEqual) throws Exception {
		Object oldvalue = BeanUtils.getProperty(o1, name);
		Object newvalue = BeanUtils.getProperty(o2, name);
		if (oldvalue == null) {
			oldvalue = "";
		}
		if (newvalue == null) {
			newvalue = "";
		}
		boolean isEqual = oldvalue.equals(newvalue);
		StringBuffer sb = new StringBuffer();
		if (isEqual && logIfEqual || !isEqual) {
			sb.append("<field name=\"").append(name).append("\">");
			sb.append("<changed>").append(isEqual ? "N" : "Y").append("</changed>");
			sb.append("<oldvalue>").append(oldvalue).append("</oldvalue>");
			sb.append("<newvalue>").append(newvalue).append("</newvalue>");
			sb.append("</field>");
		}
		return sb.toString();
	}
	/**
	 * 比较对象是否修改过，true:修改过，false:没修改过
	 * @param o1
	 * @param o2
	 * @param filedNames
	 * @return
	 * @throws Exception
	 */
	public static boolean compareObjects(Object o1, Object o2, String filedNames) throws Exception {
		Object oldvalue, newvalue;
		for (String fieldName : filedNames.split(",")) {
			oldvalue = BeanUtils.getProperty(o1, fieldName);
			newvalue = BeanUtils.getProperty(o2, fieldName);
			if (oldvalue == null) {
				oldvalue = "";
			}
			if (newvalue == null) {
				newvalue = "";
			}
			if (!oldvalue.equals(newvalue)) {
				return true;
			}
		}
		return false;
	}
	/**
	 *  从日志xml文件解析出对应的字段修改信息
	 * @param xml 需解析的xml文件
	 * @param className 数据表对应的类名，必传
	 * @param recordId 记录ID,可以不传
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static List<LogFieldInfo> getFieldInfoFromXml(String xml, String className, String recordId) throws Exception {
		List<LogFieldInfo> list = new ArrayList<LogFieldInfo>();
		SAXReader reader = new SAXReader();
		Document document = reader.read(new ByteArrayInputStream(xml.getBytes()));
		Element root = document.getRootElement();
		List<Element> classList = root.elements();
		LogFieldInfo logFieldInfo;
		for (Element e : classList) {
			String _className = e.attributeValue("name");
			if (className.equals(_className)) {
				List<Element> recordList = e.elements();
				for (Element e2 : recordList) {
					String id = e2.attributeValue("id");
					if (recordId == null || recordId.equals(id)) {
						List<Element> fieldList = e2.elements();
						for (Element e3 : fieldList) {
							logFieldInfo = new LogFieldInfo();
							logFieldInfo.setRecordId(Long.valueOf(id));
							logFieldInfo.setFieldName(e3.attributeValue("name"));
							List<Element> vList = e3.elements();
							for (Element e4 : vList) {
								String name = e4.getName();
								String value = e4.getText();
								if (name.equals("changed")) {
									logFieldInfo.setChanged(value);
								}
								else if (name.equals("oldvalue")) {
									logFieldInfo.setOldvalue(value);
								}
								else if (name.equals("newvalue")) {
									logFieldInfo.setNewvalue(value);
								}
							}
							list.add(logFieldInfo);
						}
					}
				}
				return list;
			}
		}
		return list;
	}
	public static void main(String[] args) {
		try {
			List<LogFieldInfo> list = getFieldInfoFromXml(testXml, "DeliveryFeeContract", "47");
			System.out.println(list.size());
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
}
